package client_tree;

import utils.Constants;
import client.ClientApplication;

/**
 * Klasa koja predstavlja model podataka klijent aplikacije. Sadrzi po jednu instancu klase
 * ClientModelNode, za online i offline korisnike. Na ovaj nacin se objedinjuju ove liste
 * korisnika u jedan jedinstveni model, sto pojednostavljuje upravljanje ovim cvorovima, sto
 * i jeste osnovni cilj ove klase. Klasa sadrzi metode za dodavanje i brisanje elemenata (User)
 * iz ovih lista, sa odgovarajucom kontrolom i proverom greske.
 * 
 * @author UrosKrkic & Radivoje Popovic
 */
public class ClientModel implements Constants {

	/**
	 * Referenca na objekat aplikacije.
	 */
	private ClientApplication theApp;
	
	/**
	 * Cvor stabla za Online korisnike (online, busy, away)
	 */
	private ClientModelNode online;
	
	/**
	 * Cvor stabla za Offline korisnike.
	 */
	private ClientModelNode offline;
	
	
	/**
	 * Konstruktor.
	 * @param theApp - referenca na objekat aplikacije
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public ClientModel(ClientApplication theApp) {
		this.theApp = theApp;
		
		// kreiranje online i offline cvorova stabla
		online = new ClientModelNode("Online");
		offline = new ClientModelNode("Offline");
	}
	
	
	/**
	 * Metod vraca referencu na Online cvor stabla.
	 * @return - online cvor (skladisti online, away i busy user-e)
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public ClientModelNode getOnlineModel() {
		return this.online;
	}
	
	
	/**
	 * Metod vraca referencu na Offline cvor stabla.
	 * @return - offline cvor
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public ClientModelNode getOfflineModel() {
		return this.offline;
	}
	
	
	/**
	 * Metod dodaje novog korisnika (User objekat) u odgovarajuci cvor, u zavisnosti od
	 * statusa user-a koji se dodaje.
	 * @param user - korisnik koji se dodaje
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public void addUser(User user) {
		if (user.getStatus() == OFFLINE_STATUS || user.getStatus() == INVISIBLE_STATUS) {
			offline.add(user);
		}
		else {
			online.add(user);
		}
		
		// osvezavanje stabla (viewer-a)
		theApp.getWindow().refreshTree();
	}
	
	
	/**
	 * Metod uklanja User objekat iz odbovarajuceg cvora, u zavisnosti od statusa user-a koji
	 * se uklanja.
	 * @param user - korisnik koji se uklanja iz cvora
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public void removeUser(User user) {
		if (user == null)
			return;
		
		if (user.getStatus() == OFFLINE_STATUS || user.getStatus() == INVISIBLE_STATUS) {
			offline.remove(user);
		}
		else {
			online.remove(user);
		}
		
		// osvezavanje stabla (viewer-a)
		theApp.getWindow().refreshTree();
	}
	
	
	
	/**
	 * Metod uklanja User objekat iz odbovarajuceg cvora na prosledjenom indeksu, u zavisnosti
	 * od statusa user-a koji se uklanja.
	 * @param index - indeks User objekta (cvora) koji se uklanja
	 * @param status - statu User objekta koji se uklanja
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public void removeUserAt(int index, int status) {
		switch (status) {
			case ONLINE_STATUS:
			case AWAY_STATUS:
			case BUSY_STATUS:
				if (online.getUserCount() <= 0 || index >= online.getUserCount())
					return;
				online.remove(index);
				break;
			case OFFLINE_STATUS:
			case INVISIBLE_STATUS:
				if (offline.getUserCount() <= 0 || index >= offline.getUserCount())
					return;
				offline.remove(index);
				break;
		}
		
		// osvezavanje stabla (viewer-a)
		theApp.getWindow().refreshTree();
	}
	
	
	/**
	 * Metod vraca User objekat (korisnika) na prosledjenom indeksu, u zavisnosti od njegovo
	 * statusa.
	 * @param index - zahtevani indeks po kome se cvor dobija
	 * @param status - status, po kome se odreduje vrsta korisnika koji se vraca, odnosno
	 * odredjuje se iz kog parenta (online ili offline) ce se uzimati cvor
	 * @return - cvor na trazenom indeksu ili null
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public User getUserAt(int index, int status) {
		switch (status) {
			case ONLINE_STATUS:
			case AWAY_STATUS:
			case BUSY_STATUS:
				if (online.getUserCount() <= 0 || index >= online.getUserCount())
					return null;
				return (User) online.getChildAt(index);

			case OFFLINE_STATUS:
			case INVISIBLE_STATUS:
				if (offline.getUserCount() <= 0 || index >= offline.getUserCount())
					return null;
				return (User) offline.getChildAt(index);
		}
		
		return null;
	}
	
	
	
	
	/**
	 * Metod prazni model podataka, tj. brise svu decu Online i Offline cvorova.
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public void clearModel() {
		try {
			online.removeAllChildren();
			offline.removeAllChildren();
		}
		catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}
	
	
}
